package de.idgard.android.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 
 * @author ckaratza Common Reflection Utilities
 * 
 */

public final class ReflectionUtils {

	private ReflectionUtils() {

	}

	public static Integer getIntegerField(Object obj, String name) {
		try {
			return (Integer) getDeclaredField(obj, name);
		} catch (Exception ex) {
			throw new RuntimeException(ex.getMessage());
		}
	}

	public static Boolean getBooleanField(Object obj, String name) {
		try {
			return (Boolean) getDeclaredField(obj, name);
		} catch (Exception ex) {
			throw new RuntimeException(ex.getMessage());
		}
	}

	public static Object getDeclaredField(Object obj, String name) {
		try {
			Field f = obj.getClass().getDeclaredField(name);
			f.setAccessible(true);
			Object out = f.get(obj);
			return out;
		} catch (Exception ex) {
			throw new RuntimeException(ex.getMessage());
		}
	}

	public static Object getDeclaredFieldOfSuperClass(Object obj, String name) {
		try {
			Field f = obj.getClass().getSuperclass().getDeclaredField(name);
			f.setAccessible(true);
			Object out = f.get(obj);
			return out;
		} catch (Exception ex) {
			throw new RuntimeException(ex.getMessage());
		}
	}

	public static void setDeclaredField(Object obj, String name, Object value) {
		try {
			Field f = obj.getClass().getDeclaredField(name);
			f.setAccessible(true);
			f.set(obj, value);
		} catch (Exception ex) {
			throw new RuntimeException(ex.getMessage());
		}
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static Object invokeMethod(Object object, String methodName, Object[] params, Class... types) {
		try {
			Object out = null;
			Class c = object instanceof Class ? (Class) object : object.getClass();
			if (types != null) {
				Method method = null;
				try {
					method = c.getDeclaredMethod(methodName, types);
				} catch (Exception ex) {
				}
				if (method == null) {
					method = c.getSuperclass().getDeclaredMethod(methodName, types);
				}
				method.setAccessible(true);
				out = method.invoke(object, params);
			} else {
				Method method = null;
				try {
					method = c.getDeclaredMethod(methodName);
				} catch (Exception ex) {
				}
				if (method == null) {
					method = c.getSuperclass().getDeclaredMethod(methodName, types);
				}
				method.setAccessible(true);
				out = method.invoke(object);
			}
			return out;
		} catch (Exception ex) {
			ex.printStackTrace();
			throw new RuntimeException(ex.getMessage());
		}
	}
}
